using System;
using System.Collections;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Threading;

namespace Framework.Library.Core.Utils.GlobalHelper
{
    public static class ValidationHelper
    {
        private static Regex mCodenameRegExp;
        private static readonly Hashtable mDoubleExps = new Hashtable();
        private static Regex mEmailRegExp;
        private static Regex mFilenameRegExp;
        private static Regex mIdentificatorRegExp;
        private static Regex mIntRegExp;
        public static DateTime DATETIME_NOT_SELECTED = new DateTime(0L);

        public static Regex CodenameRegExp
        {
            get
            {
                if (mCodenameRegExp == null)
                {
                    mCodenameRegExp = new Regex(@"^([A-Za-z0-9_-]+)(\.[A-Za-z0-9_-]+)*$", RegexOptions.Compiled);
                }
                return mCodenameRegExp;
            }
            set { mCodenameRegExp = null; }
        }

        public static Regex EmailRegExp
        {
            get
            {
                if (mEmailRegExp == null)
                {
                    mEmailRegExp =
                        new Regex(@"^[A-Za-z0-9_\-\+]+(\.[A-Za-z0-9_\-\+]+)*@[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)+$",
                                  RegexOptions.Compiled);
                }
                return mEmailRegExp;
            }
            set { mEmailRegExp = null; }
        }

        public static Regex FilenameRegExp
        {
            get
            {
                if (mFilenameRegExp == null)
                {
                    mFilenameRegExp = new Regex(@"^[A-Za-z][A-Za-z0-9\._-]*$", RegexOptions.Compiled);
                }
                return mFilenameRegExp;
            }
            set { mFilenameRegExp = null; }
        }

        public static Regex IdentificatorRegExp
        {
            get
            {
                if (mIdentificatorRegExp == null)
                {
                    mIdentificatorRegExp = new Regex("^[A-Za-z][A-Za-z0-9_]*$", RegexOptions.Compiled);
                }
                return mIdentificatorRegExp;
            }
            set { mIdentificatorRegExp = null; }
        }

        public static Regex IntRegExp
        {
            get
            {
                if (mIntRegExp == null)
                {
                    mIntRegExp = new Regex(@"^(\+|-)?\d+$", RegexOptions.Compiled);
                }
                return mIntRegExp;
            }
            set { mIntRegExp = null; }
        }

        public static bool AreEmails(object value)
        {
            if ((value == DBNull.Value) || (value == null))
            {
                return false;
            }
            foreach (string str in value.ToString().Split(new[] {';'}))
            {
                if (!IsEmail(str))
                {
                    return false;
                }
            }
            return true;
        }

        public static byte[] GetBinary(object value, byte[] defaultValue)
        {
            if ((value == DBNull.Value) || (value == null))
            {
                return defaultValue;
            }
            try
            {
                return (byte[]) value;
            }
            catch
            {
                return defaultValue;
            }
        }

        public static bool GetBoolean(object value, bool defaultValue)
        {
            if ((value == null) || (value == DBNull.Value))
            {
                return defaultValue;
            }
            if (value is bool)
            {
                return (bool) value;
            }
            if (!(value is string))
            {
                return Convert.ToBoolean(value);
            }
            string str = ((string) value).ToLower();
            if (str == null)
            {
                return defaultValue;
            }
            if (!(str == "true") && !(str == "1"))
            {
                if ((str == "false") || (str == "0"))
                {
                    return false;
                }
                return defaultValue;
            }
            return true;
        }

        public static string GetCodeName(object name)
        {
            return GetCodeName(name, null);
        }

        public static string GetCodeName(object name, string replacement)
        {
            if (replacement == null)
            {
                replacement = "_";
            }
            return Regex.Replace(GetString(name, ""), "[^a-zA-Z0-9_.]+", replacement);
        }

        public static DateTime GetDateTime(object value, DateTime defaultValue)
        {
            return GetDateTime(value, defaultValue, null);
        }

        public static DateTime GetDateTime(object value, DateTime defaultValue, IFormatProvider format)
        {
            if ((value == DBNull.Value) || (value == null))
            {
                return defaultValue;
            }
            if (value is DateTime)
            {
                return (DateTime) value;
            }
            try
            {
                return DateTime.Parse(value.ToString(), format);
            }
            catch
            {
                return defaultValue;
            }
        }

        public static double GetDouble(object value, double defaultValue)
        {
            return GetDouble(value, defaultValue, null);
        }

        public static double GetDouble(object value, double defaultValue, string culture)
        {
            if (!IsDouble(value, culture))
            {
                return defaultValue;
            }
            if (culture != null)
            {
                var provider = new CultureInfo(culture);
                return Convert.ToDouble(value, provider);
            }
            return Convert.ToDouble(value);
        }

        private static Regex GetDoubleExp()
        {
            return GetDoubleExp(null);
        }

        private static Regex GetDoubleExp(string culture)
        {
            CultureInfo currentUICulture = null;
            if (culture == null)
            {
                currentUICulture = Thread.CurrentThread.CurrentUICulture;
                culture = currentUICulture.IetfLanguageTag;
            }
            var regex = (Regex) mDoubleExps[culture];
            if (regex == null)
            {
                if (currentUICulture == null)
                {
                    currentUICulture = new CultureInfo(culture);
                }
                regex =
                    new Regex(
                        @"^(\+|-)?(\d*\" + currentUICulture.NumberFormat.NumberDecimalSeparator +
                        @"?\d+)((e|E)(\+|-)?\d+)?$", RegexOptions.Compiled);
                mDoubleExps[culture] = regex;
            }
            return regex;
        }

        public static Guid GetGuid(object value, Guid defaultValue)
        {
            if ((value == DBNull.Value) || (value == null))
            {
                return defaultValue;
            }
            if (value is Guid)
            {
                return (Guid) value;
            }
            try
            {
                return new Guid(value.ToString());
            }
            catch
            {
                return defaultValue;
            }
        }

        public static string GetIdentificator(object name)
        {
            return GetIdentificator(name, null);
        }

        public static string GetIdentificator(object name, string replacement)
        {
            if (replacement == null)
            {
                replacement = "_";
            }
            return Regex.Replace(GetString(name, ""), "[^a-zA-Z0-9_]", replacement);
        }

        public static int GetInteger(object value, int defaultValue)
        {
            if (!IsInteger(value))
            {
                return defaultValue;
            }
            return Convert.ToInt32(value);
        }

        public static int GetSafeInteger(object value, int defaultValue)
        {
            try
            {
                return GetInteger(value, defaultValue);
            }
            catch
            {
                return defaultValue;
            }
        }

        public static string GetString(object value, string defaultValue)
        {
            if ((value != DBNull.Value) && (value != null))
            {
                return value.ToString();
            }
            return defaultValue;
        }

        public static bool IsBoolean(object value)
        {
            string str;
            if ((value == DBNull.Value) || (value == null))
            {
                return false;
            }
            if (!(value is bool) &&
                (((str = value.ToString().ToLower()) == null) ||
                 ((!(str == "0") && !(str == "1")) && (!(str == "true") && !(str == "false")))))
            {
                return false;
            }
            return true;
        }

        public static bool IsCodeName(object value)
        {
            return (((value != DBNull.Value) && (value != null)) && CodenameRegExp.Match(value.ToString()).Success);
        }

        public static bool IsDouble(object value)
        {
            return IsDouble(value, null);
        }

        public static bool IsDouble(object value, string culture)
        {
            if ((value == DBNull.Value) || (value == null))
            {
                return false;
            }
            return ((value is double) || GetDoubleExp(culture).Match(value.ToString()).Success);
        }

        public static bool IsEmail(object value)
        {
            return (((value != DBNull.Value) && (value != null)) && EmailRegExp.Match(value.ToString()).Success);
        }

        public static bool IsFileName(object value)
        {
            return (((value != DBNull.Value) && (value != null)) && FilenameRegExp.Match(value.ToString()).Success);
        }

        public static bool IsGuid(object value)
        {
            if ((value == DBNull.Value) || (value == null))
            {
                return false;
            }
            return (GetGuid(value, Guid.Empty) != Guid.Empty);
        }

        public static bool IsIdentificator(object value)
        {
            return (((value != DBNull.Value) && (value != null)) && IdentificatorRegExp.Match(value.ToString()).Success);
        }

        public static bool IsInteger(object value)
        {
            if ((value == DBNull.Value) || (value == null))
            {
                return false;
            }
            return ((value is int) || IntRegExp.Match(value.ToString()).Success);
        }

        public static bool IsIntervalValid(DateTime fromDate, DateTime toDate, bool nullFriendly)
        {
            fromDate = GetDateTime(fromDate, DATETIME_NOT_SELECTED);
            toDate = GetDateTime(toDate, DATETIME_NOT_SELECTED);
            if (!nullFriendly)
            {
                return (fromDate <= toDate);
            }
            if (!(fromDate == DATETIME_NOT_SELECTED) && !(toDate == DATETIME_NOT_SELECTED))
            {
                return (fromDate <= toDate);
            }
            return true;
        }

        public static bool IsPositiveNumber(object value)
        {
            if ((value == DBNull.Value) || (value == null))
            {
                return false;
            }
            if (!IntRegExp.Match(value.ToString()).Success && !GetDoubleExp().Match(value.ToString()).Success)
            {
                return false;
            }
            return !value.ToString().StartsWith("-");
        }
    }
}